package com.graduation.project.service.system.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.graduation.project.entity.dto.user.ListUserDTO;
import com.graduation.project.entity.dto.user.SaveOrUpdateUserDTO;
import com.graduation.project.entity.dto.UpdateStatusDTO;
import com.graduation.project.entity.dto.UpdateUserInfoByMySelfDTO;
import com.graduation.project.entity.other.LoginUser;
import com.graduation.project.entity.po.Role;
import com.graduation.project.entity.po.Unit;
import com.graduation.project.entity.po.User;
import com.graduation.project.entity.po.UserRole;
import com.graduation.project.entity.vo.ListOptionsVO;
import com.graduation.project.entity.vo.user.ListUserVO;
import com.graduation.project.entity.vo.UserDetailsVO;
import com.graduation.project.enums.ResultCodeEnum;
import com.graduation.project.mapper.system.RoleMapper;
import com.graduation.project.mapper.system.UnitMapper;
import com.graduation.project.mapper.system.UserMapper;
import com.graduation.project.service.system.UserManagementService;
import com.graduation.project.service.system.UserRoleService;
import com.graduation.project.utils.ResultUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author 卑微小峰
 * @date 2022/11/05
 * 用户管理业务实现类
 */
@Service
public class UserManagementServiceImpl extends ServiceImpl<UserMapper, User> implements UserManagementService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private UserRoleService userRoleService;

    @Autowired
    private UnitMapper unitMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultUtil<?> addUser(SaveOrUpdateUserDTO input) {

        // 判断数据库是否已存在该用户
        LambdaQueryWrapper<User> lambdaQueryUserWrapper = new LambdaQueryWrapper<>();
        lambdaQueryUserWrapper.eq(User::getUserCode, input.getUserCode());

        if (ObjectUtil.isNotEmpty(userMapper.selectOne(lambdaQueryUserWrapper))) {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "此用户已存在");
        }

        User user = new User();
        BeanUtil.copyProperties(input, user, "id");
        // 设置初始密码为账号,密码加密
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        user.setUserPassword(passwordEncoder.encode(user.getUserCode()));

        try {
            // 新增用户
            userMapper.insert(user);
            // 新增用户角色关系
            List<UserRole> userRoleList = new ArrayList<>();
            List<Long> roleIds = input.getRoleIds();
            roleIds.forEach(roleId -> {
                UserRole userRole = new UserRole();
                userRole.setUserId(user.getId());
                userRole.setRoleId(roleId);
                userRoleList.add(userRole);
            });
            userRoleService.saveBatch(userRoleList);
        } catch (Exception e) {
            throw new RuntimeException("新增用户失败");
        }
        return ResultUtil.Success(ResultCodeEnum.SUCCESS.getCode(), "新增成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultUtil<?> updateUser(SaveOrUpdateUserDTO input) {
        if (ObjectUtil.isEmpty(input.getId())) {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "参数不能为空");
        }
        // 判断修改用户是否存在
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getId, input.getId());
        User user = userMapper.selectOne(queryWrapper);
        if (ObjectUtil.isEmpty(user)) {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "修改数据不存在");
        }
        // 判断是否账号是否被修改，如果修改，判断数据库中是否已存在当前修改的值
        if (!input.getUserCode().equals(user.getUserCode())) {
            queryWrapper.clear();
            queryWrapper.eq(User::getUserCode, input.getUserCode());
            if (ObjectUtil.isNotEmpty(userMapper.selectOne(queryWrapper))) {
                return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "账号已存在");
            }
        }

        BeanUtil.copyProperties(input, user);
        try {
            // 修改用户基本信息
            userMapper.updateById(user);
            // 修改用户角色关系：
            // 1、删除此用户所有关系
            userRoleService.remove(new LambdaQueryWrapper<UserRole>().eq(UserRole::getUserId, input.getId()));
            // 2、新增用户角色关系
            List<UserRole> userRoleList = new ArrayList<>();
            List<Long> roleIds = input.getRoleIds();
            roleIds.forEach(roleId -> {
                UserRole userRole = new UserRole();
                userRole.setUserId(input.getId());
                userRole.setRoleId(roleId);
                userRoleList.add(userRole);
            });
            userRoleService.saveBatch(userRoleList);
        } catch (Exception e) {
            throw new RuntimeException("修改失败");
        }
        return ResultUtil.Success(ResultCodeEnum.SUCCESS.getCode(), "修改成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultUtil<?> deleteUserById(List<Long> idList) {
        try {
            userMapper.deleteBatchIds(idList);
            // 删除用户角色关系信息
            for (Long id : idList) {
                userRoleService.remove(new LambdaQueryWrapper<UserRole>().eq(UserRole::getUserId, id));
            }
        } catch (Exception e) {
            throw new RuntimeException("删除失败");
        }
        return ResultUtil.Success(ResultCodeEnum.SUCCESS.getCode(), "删除成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultUtil<?> updateUserStatusById(UpdateStatusDTO input) {
        // 判断修改数据是否存在
        User user = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getId, input.getId()));
        if (ObjectUtil.isEmpty(user)) {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "修改数据不存在");
        }
        user.setUserStatus(input.getStatus());
        try {
            userMapper.updateById(user);
        }catch (Exception e) {
            throw new RuntimeException("操作失败");
        }
        return ResultUtil.Success(ResultCodeEnum.SUCCESS.getCode(), "操作成功");
    }

    @Override
    public ResultUtil<?> listRoleByCondition(ListUserDTO input) {
        IPage<User> page = new Page<>();
        page.setCurrent(input.getCurrentPage());
        page.setSize(input.getPageSize());

        // 获取当前用户id，查询用户列表时排除自己
        UsernamePasswordAuthenticationToken authenticationToken = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authenticationToken.getPrincipal();
        Long id = loginUser.getUser().getId();

        LambdaQueryWrapper<User> lambdaQueryUserWrapper = new LambdaQueryWrapper<>();
        lambdaQueryUserWrapper.like(StringUtils.isNotBlank(input.getUserName()), User::getUserName, input.getUserName())
                .like(StringUtils.isNotBlank(input.getUserCode()), User::getUserCode, input.getUserCode())
                .eq(input.getUserStatus() != null, User::getUserStatus, input.getUserStatus())
                .ne(User::getId, id);

        userMapper.selectPage(page, lambdaQueryUserWrapper);

        Map<String, Object> map = new HashMap<>();
        map.put("total", page.getTotal());

        List<ListUserVO> listUserVo = page.getRecords().stream()
                .map(user -> {
                    ListUserVO listUserVO = new ListUserVO();
                    BeanUtil.copyProperties(user, listUserVO);
                    return listUserVO;
                })
                .collect(Collectors.toList());
        map.put("listUserVo", listUserVo);
        return ResultUtil.Success(ResultCodeEnum.SUCCESS.getCode(), "查询成功", map);
    }

    @Override
    public ResultUtil<?> listUserRoleByUserId(Long userId) {
        LambdaQueryWrapper<UserRole> lambdaQueryUserRoleWrapper = new LambdaQueryWrapper<>();
        lambdaQueryUserRoleWrapper.eq(UserRole::getUserId, userId);
        List<UserRole> userRoleList = userRoleService.list(lambdaQueryUserRoleWrapper);
        List<Long> roleIds = userRoleList.stream()
                .map(UserRole::getRoleId)
                .collect(Collectors.toList());
        return ResultUtil.Success(ResultCodeEnum.SUCCESS, roleIds);
    }

    @Override
    public ResultUtil<?> listRoleOptions() {
        List<Role> roleList = roleMapper.selectList(new LambdaQueryWrapper<Role>()
                .select(
                        Role::getId,
                        Role::getRoleName,
                        Role::getRoleStatus
                ));
        List<ListOptionsVO> output = new ArrayList<>();
        if (CollUtil.isNotEmpty(roleList)) {
            output = roleList.stream()
                    .map(role -> {
                        ListOptionsVO listOptionsVO = new ListOptionsVO();
                        listOptionsVO.setValue(role.getId());
                        listOptionsVO.setLabel(role.getRoleName());
                        listOptionsVO.setStatus(role.getRoleStatus());
                        return listOptionsVO;
                    })
                    .collect(Collectors.toList());
        }
        return ResultUtil.Success(ResultCodeEnum.SUCCESS, output);
    }

    @Override
    public ResultUtil<?> listUnitOptions() {
        List<Unit> unitList = unitMapper.selectList(new LambdaQueryWrapper<Unit>()
                .select(
                        Unit::getId,
                        Unit::getUnitName,
                        Unit::getParentUnitId,
                        Unit::getUnitStatus
                ));
        List<ListOptionsVO> output = new ArrayList<>();
        if (CollUtil.isNotEmpty(unitList)) {
            output = unitList.stream()
                    .map(unit -> {
                        ListOptionsVO listOptionsVO = new ListOptionsVO();
                        listOptionsVO.setValue(unit.getId());
                        listOptionsVO.setLabel(unit.getUnitName());
                        listOptionsVO.setParentId(unit.getParentUnitId());
                        listOptionsVO.setStatus(unit.getUnitStatus());
                        return listOptionsVO;
                    })
                    .collect(Collectors.toList());
        }
        return ResultUtil.Success(ResultCodeEnum.SUCCESS, output);
    }

    @Override
    public ResultUtil<?> resetUserPassword(Long id, String password) {
        // 判断修改数据是否存在
        User user = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getId, id));
        if (ObjectUtil.isEmpty(user)) {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "修改数据不存在");
        }
        // 密码加密处理
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        String userPassword = passwordEncoder.encode(password);

        user.setUserPassword(userPassword);
        try {
            userMapper.updateById(user);
        }catch (Exception e) {
            throw new RuntimeException("重置失败");
        }
        return ResultUtil.Success(ResultCodeEnum.SUCCESS.getCode(), "重置密码成功");
    }


    /**
     * 给用户分配角色
     * @param id 用户id
     * @param idList 角色id集合
     * @return ResultUtil
     */
    @Override
    public ResultUtil<?> assignRoleToUser(Long id, List<Long> idList) {
        return null;
    }

    @Override
    public ResultUtil<?> download() {
//        List<Person> list = new ArrayList<>();
//        list.add(new Person());
        ExcelWriter writer = ExcelUtil.getWriter("C:\\Users\\admin\\Desktop\\xxxx.xls");
        writer.addHeaderAlias("id", "编号");
        writer.addHeaderAlias("name", "姓名");
        writer.addHeaderAlias("age", "年龄");

//        writer.write(list);
//        writer.write(arrayList);
        writer.close();
        return null;
    }

    @Override
    public ResultUtil<?> getUserInfoDetails(String userCode) {
        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(User::getUserCode, userCode);
        User user = userMapper.selectOne(lambdaQueryWrapper);

        UserDetailsVO userDetailsVO = new UserDetailsVO();
        BeanUtil.copyProperties(user, userDetailsVO);
        userDetailsVO.setUserIdentity(DesensitizedUtil.idCardNum(user.getUserIdentity(), 3, 4));
        userDetailsVO.setUserPhone(DesensitizedUtil.mobilePhone(user.getUserPhone()));
        // 单位
        LambdaQueryWrapper<Unit> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Unit::getId, user.getUnitId());
        Unit unit = unitMapper.selectOne(queryWrapper);
        if (ObjectUtil.isNotEmpty(unit)) {
            userDetailsVO.setUnitName(unit.getUnitName());
        }
        return ResultUtil.Success(ResultCodeEnum.SUCCESS.getCode(), "查询成功", userDetailsVO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultUtil<?> updateUserInfoByMySelf(UpdateUserInfoByMySelfDTO updateUserInfoByMySelfDTO) {
        User user = new User();
        BeanUtil.copyProperties(updateUserInfoByMySelfDTO, user);
        try {
            userMapper.updateById(user);
        }catch (Exception e) {
            throw new RuntimeException("修改失败");
        }
        return ResultUtil.Success(ResultCodeEnum.SUCCESS.getCode(), "修改成功");
    }

    @Override
    public ResultUtil<?> uploadAvatar(MultipartFile file) {
        // 获取用户信息
        UsernamePasswordAuthenticationToken authenticationToken = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authenticationToken.getPrincipal();
        // 拼接上传路径（绝对路径）：/zyf_file/账号
        String path = "F:/graduation-project/frontend/graduation-project/public/static/zyf_file/" + loginUser.getUser().getUserCode() + "/avatar";
        File filePath = new File(path);
        if (!filePath.exists()) {
            filePath.mkdirs();
        }

        // 获取用户上传文件后缀，并通过uuid命名文件
        String fileName = file.getOriginalFilename();
        String suffix = fileName.substring(fileName.lastIndexOf("."));
        fileName = IdUtil.simpleUUID() + suffix;

        LambdaUpdateWrapper<User> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.set(User::getUserAvatar, "../../../public/static/zyf_file/" + loginUser.getUser().getUserCode() + "/avatar/" + fileName)
                .eq(User::getUserCode, loginUser.getUser().getUserCode());
        try {
            file.transferTo(new File(filePath, fileName));
            // 保存到数据库（保存相对路径）
            userMapper.update(null, lambdaUpdateWrapper);
        }catch (Exception e) {
            return ResultUtil.Failed(ResultCodeEnum.FILED.getCode(), "上传失败");
        }
        return ResultUtil.Success(ResultCodeEnum.SUCCESS.getCode(), "上传成功");
    }
}
